﻿using System;
using Algoritmia.Utils.Numerics;

namespace Algoritmia.SemiRings
{
    public class CountingSemiRing<T> : IIdempotentSemiRing<T>
        where T : IComparable<T>
    {
        private readonly IArithmeticsProvider<T> _arithmeticsProvider;
        private static CountingSemiRing<T> _instance;

        private CountingSemiRing(Func<IArithmeticsProvider<T>> createArithmeticsProvider = null)
        {
            createArithmeticsProvider = createArithmeticsProvider ?? (() => new BuiltinNumericsArithmeticsProvider<T>());
            _arithmeticsProvider = createArithmeticsProvider();   
        }

        public static CountingSemiRing<T> GetInstance(Func<IArithmeticsProvider<T>> createArithmeticsProvider = null)
        {
            _instance = _instance ?? new CountingSemiRing<T>(createArithmeticsProvider);
            return _instance;
        }

        #region Implementation of ISemiRing<T>

        public T Zero
        {
            get { return _arithmeticsProvider.Zero; }
        }

        public T One
        {
            get { return _arithmeticsProvider.One; }
        }

        public T Plus(T left, T right)
        {
            return (T) _arithmeticsProvider.Add(left, right);
        }

        public T Times(T left, T right)
        {
            return (T) _arithmeticsProvider.Multiply(left, right);
        }

        #endregion
    }
}
